Using Econet

by Glenn Richards

 

 

  This article will explain how to write programs that use Econet as a device, rather than just as a filing system.


SWIs

There are 6 SWIs that we shall be using:
   Econet_CreateReceive
   Econet_ExamineReceive
   Econet_AbandonReceive
   Econet_WaitForReception
   Econet_DoTransmit
   Econet_ReadLocalStationAndNet

These names are fairly obvious.


Initialisation

If you are planning to receive data over the network you will need to set up a receive buffer. The obvious way to do this would be:
   DIM rxcb% 2048

This however will not work unless your program is non-multitasking, the reason being that data is read by RISC OS itself, not the application. The Econet module within RISC OS will attempt to write to the address given, but because the MEMC has remapped it will overwrite another application and may cause a complete system crash.

The solution is to claim workspace in the RMA. The following SWI will do the trick:

   SYS "OS_Module",6,,,2048 TO rxcb%

You can define your transmit buffer in the normal way, ie:

   DIM txcb% 2048

as RISC OS makes a copy of the transmit block before starting the transmit operation.

Next we need to add some library procedures:

   PROCgetstationaddress
   FNcreaterx
   FNgetrxdata
   FNrxstatus
   FNwaitforrx
   PROCtransmit


Receiving Data

PROCgetstationaddress returns the local network (will always be 0 unless you have a bridge) and station number of your machine:
   DEFPROCgetstationaddress(RETURN net%,RETURN station%)
     SYS "Econet_ReadLocalStationAndNet" TO station%,net%
   ENDPROC

It should be called as your program is initialising, like this:

   net%=0
   station%=0
   PROCgetstationaddress(net%,station)

Now on to the receive functions. FNcreaterx will create a receive block, returning the block handle:

   DEFFNcreaterx(port%,station%,net%)
     LOCAL rxhandle%
     SYS "Econet_CreateReceive",port%,station%,net%,rxcb%,2048 TO rxhandle%
   =rxhandle%

FNgetrxdata reads back any received data from the given block handle as a string:

   DEFFNgetrxdata(rxhandle%)
     LOCAL rxdata%,bytes%,rxdata$
     SYS "Econet_ReadReceive",rxhandle% TO ,,,,,rxdata%,bytes%
     rxdata%?bytes%=13
     rxdata$=$rxdata%
     SYS "Econet_AbandonReceive",rxhandle%
   =rxdata$

FNrxstatus will return TRUE if data has been received on the given handle or FALSE if either no data has been received or a reception is currently in progress:

   DEFFNrxstatus(rxhandle%)
     LOCAL status%
     SYS "Econet_ExamineReceive",rxhandle% TO status%
     IF status%=9 =TRUE ELSE =FALSE

The final receive function, FNwaitforrx, will wait until either data is received from the given station and port number or a specified timeout (in centiseconds) is reached, in which case it will return a null string.

   DEFFNwaitforrx(port%,station%,net%,time%)
     LOCAL rxhandle%,rxdata%,bytes%,status%
     SYS "Econet_CreateReceive",port%,station%,net%,rxcb%,2048 TO rxhandle%
     SYS "Econet_WaitForReception",rxhandle%,time%,0 TO status%,,,,,rxdata%,bytes%
     IF status%=10 =""
     rxdata%?bytes%=13
   =$rxdata%


Transmitting

Finally the transmit procedure:
   DEFPROCtransmit(port%,station%,net%,txdata$)
     $txcb%=txdata$
     SYS "Econet_DoTransmit",0,port%,station%,net%,txcb%,LEN(txdata$),64,2
   ENDPROC

The last 2 numbers on the DoTransmit SWI are the number of retries and the delay between retries in centiseconds; in this example it will try 64 times to transmit with a 2 cenisecond delay between each attempt.

Ok, that's all very well, but how do you use them?

The best way is, as ever, to have a very short example program. It will multitask, but will not have any windows, icons or menus. It will simply record everything transmitted on port 128 into a file in the CSD.

Note that if you specify to receive from station 0, you will be able to receive from any station on your network (ie not from across a bridge).

Yes, I know this doesn't comply with the style guide, but it's only a demonstration!

   DIM taskid% 4,block% 2048
   $taskid%="TASK"

   SYS "OS_Module",6,,,2048 TO ,,rxcb%
   SYS "Wimp_Initialise",200,!taskid%,"Econet demo"

   quit%=FALSE

   station%=0
   net%=0
   port%=128
   rxhandle%=FNcreaterx(port%,station%,net%)

   file%=OPENOUT"NetData"

   REPEAT
     SYS "Wimp_Poll,,block% TO action%
     CASE action% OF
       WHEN 0     : IF FNrxstatus THEN PROCdatareceived
       WHEN 17,18 : IF block%!16=0 quit%=TRUE
     ENDCASE
   UNTIL quit%

   CLOSE#file%

   IF rxcb%<>-1 THEN SYS "XOS_Module",7,,rxcb%

   END

You will need to add the procedure PROCdatareceived to the program later, but first a quick description.

The first few lines are just a standard WIMP application header, the third line claims workspace from RMA. Notice that you should set up the receive block before the start of the main polling loop, otherwise you will get an "Unknown or missing variable" error.

When the WIMP returns control with a reason code of 0 (ie a null poll) this is when you chech the state of the receive block with FNrxstatus. If the result returns TRUE it calls the procedure PROCdatareceived, which we shall come to in a short time.

You can quit this program from the Task Manager (reason codes 17 and 18), the final line before the END releases the workspace we claimed earlier back to the RMA.

Now for the procedure PROCdatareceived:

   DEFPROCdatareceived
     LOCAL rxdata$
     rxdata$=FNgetrxdata(rxhandle%)
     rxhandle%=FNcreaterx%(port%,station%,net%)
     BPUT#file%,rxdata$
   ENDPROC

This is fairly straightforward, but notice the requirement to create a new receive block immediately after reading out the data. This is because once the block has been filled a new one must be created before any new data can be received.

Once the new block has been created it then writes out the received string to the file that was opened at the start of the program.

To demonstrate that it's working we shall need a transmit program, this is a very simple single-tasking affair:

   MODE 12
   DIM txcb% 2048
   port%=128
   net%=0
   INPUT "Enter station number"station%
   REPEAT
     INPUT txdata$
     PROCtransmit(port%,station%,net%,txdata$)
   UNTIL FALSE

Attach PROCtransmit above to the end of this program and run it on another station somewhere, and whatever you type should be saved into the file. Press ESCAPE to quit the transmit program.


Return to econet index


Copyright © Glenn Richards, December 1996
HTML by Richard Murray, 1999